<!--
 * @Description: 货款结算页 - 查看订单付款与收款记录、标记欠款与逾期天数
 * @Author: lujq
 * @Date: 2025-08-25
 * @LastEditors: lujq
 * @LastEditTime: 2025-08-25 14:40:00
-->
<template>
  <div class="settlement">
    <el-card class="search-card">
      <div class="search-bar">
        <el-form :inline="true" :model="searchForm" @submit.prevent>
          <el-form-item label="关键词">
            <el-input v-model="searchForm.keyword" placeholder="订单号/客户名" clearable @keyup.enter="fetchData" />
          </el-form-item>
          <el-form-item label="支付状态">
            <el-select v-model="searchForm.paymentStatus" placeholder="全部" clearable style="width: 140px">
              <el-option label="未支付" value="unpaid" />
              <el-option label="部分支付" value="partial" />
              <el-option label="已支付" value="paid" />
              <el-option label="已退款" value="refunded" />
            </el-select>
          </el-form-item>
          <el-form-item label="订单日期">
            <el-date-picker v-model="searchForm.dateRange" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" value-format="YYYY-MM-DD" />
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="fetchData">查询</el-button>
            <el-button @click="resetSearch">重置</el-button>
          </el-form-item>
        </el-form>
      </div>
    </el-card>

    <el-card class="table-card" style="margin-top: 16px;">
      <template #header>
        <div class="header-row">
          <span>订单收款与结算</span>
          <div>
            <el-tag type="danger" v-if="summary.overdueCount > 0">逾期订单：{{ summary.overdueCount }}</el-tag>
            <el-tag type="warning" style="margin-left: 8px;" v-if="summary.unpaidTotal > 0">未收总额：{{ summary.unpaidTotal.toFixed(2) }}</el-tag>
          </div>
        </div>
      </template>

      <el-table :data="displayRows" row-key="id" border :row-class-name="rowClassName">
        <el-table-column type="expand">
          <template #default="{ row }">
            <div class="receipt-list">
              <div class="receipt-header">
                <div>收款记录（共 {{ row.receipts.length }} 条，已收：{{ row.paidAmount.toFixed(2) }} 元）</div>
                <el-button type="primary" size="small" @click="openAddReceipt(row)">新增收款</el-button>
              </div>
              <el-table :data="row.receipts" size="small" border>
                <el-table-column prop="receiptDate" label="收款日期" width="140" />
                <el-table-column prop="amount" label="收款金额(元)" width="140" />
                <el-table-column prop="method" label="方式" width="120" />
                <el-table-column prop="remark" label="备注" min-width="160" />
                <el-table-column label="操作" width="80">
                  <template #default="{ row: r }">
                    <el-popconfirm title="确认删除该收款记录？" @confirm="deleteReceipt(r)">
                      <template #reference>
                        <el-button type="danger" link size="small">删除</el-button>
                      </template>
                    </el-popconfirm>
                  </template>
                </el-table-column>
              </el-table>
            </div>
          </template>
        </el-table-column>

        <el-table-column prop="orderNo" label="订单号" width="130" />
        <el-table-column prop="customerName" label="客户" min-width="140" />
        <el-table-column prop="finalAmount" label="订单金额(元)" width="130" />
        <el-table-column prop="paidAmount" label="已收(元)" width="120" />
        <el-table-column prop="unpaidAmount" label="未收(元)" width="120">
          <template #default="{ row }">
            <span :style="{ color: row.unpaidAmount > 0 ? '#E6A23C' : '#67C23A' }">{{ row.unpaidAmount.toFixed(2) }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="paymentStatus" label="支付状态" width="110">
          <template #default="{ row }">
            <el-tag :type="getPaymentStatusType(row.paymentStatus)" size="small">{{ getPaymentStatusTag(row.paymentStatus) }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="deliveryDate" label="交付日期" width="120" />
        <el-table-column prop="dueDate" label="应收到期日" width="120" />
        <el-table-column prop="overdueDays" label="逾期(天)" width="90">
          <template #default="{ row }">
            <el-tag v-if="row.overdueDays > 0" type="danger">{{ row.overdueDays }}</el-tag>
            <span v-else>-</span>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="180" fixed="right">
          <template #default="{ row }">
            <el-button link type="primary" size="small" @click="openAddReceipt(row)">新增收款</el-button>
            <el-button link type="warning" size="small" @click="toggleExpand(row)">收款记录</el-button>
          </template>
        </el-table-column>
      </el-table>

      <div class="pager">
        <el-pagination
          background
          layout="prev, pager, next, sizes, jumper, total"
          :total="pagination.total"
          :current-page="pagination.page"
          :page-size="pagination.pageSize"
          @current-change="onPageChange"
          @size-change="onPageSizeChange"
        />
      </div>
    </el-card>

    <el-dialog v-model="receiptDialog.visible" title="新增收款" width="480px">
      <el-form :model="receiptDialog.form" label-width="100px">
        <el-form-item label="订单号">
          <el-input v-model="receiptDialog.form.orderNo" disabled />
        </el-form-item>
        <el-form-item label="客户">
          <el-input v-model="receiptDialog.form.customerName" disabled />
        </el-form-item>
        <el-form-item label="收款金额" required>
          <el-input-number v-model="receiptDialog.form.amount" :min="0.01" :precision="2" :step="100" controls-position="right" style="width: 200px" />
          <span class="unpaid-tip">未收：{{ receiptDialog.unpaidRemain.toFixed(2) }}</span>
        </el-form-item>
        <el-form-item label="收款日期" required>
          <el-date-picker v-model="receiptDialog.form.receiptDate" type="date" placeholder="选择日期" value-format="YYYY-MM-DD" />
        </el-form-item>
        <el-form-item label="方式">
          <el-select v-model="receiptDialog.form.method" placeholder="选择方式">
            <el-option label="银行转账" value="transfer" />
            <el-option label="现金" value="cash" />
            <el-option label="支票" value="cheque" />
            <el-option label="其他" value="other" />
          </el-select>
        </el-form-item>
        <el-form-item label="备注">
          <el-input v-model="receiptDialog.form.remark" type="textarea" :rows="3" placeholder="可填写票据号等信息" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="receiptDialog.visible = false">取消</el-button>
        <el-button type="primary" :loading="receiptDialog.saving" @click="submitReceipt">保存</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script lang="ts" setup>
/**
 * @description 货款结算页逻辑：
 * - 加载订单、收款记录、客户信息并进行前端聚合
 * - 计算每个订单的已收、未收、到期日与逾期天数
 * - 支持新增收款记录并联动更新订单支付状态
 */
import { ref, reactive, computed, onMounted, nextTick } from 'vue'
import dayjs from 'dayjs'
import { ElMessage, ElMessageBox } from 'element-plus'
import { http } from '@/api/index'
import { getOrderList, updatePaymentStatus } from '@/api/order'
import { getPaymentStatusTag } from '@/utils'
import type { Order, Customer, Receipt } from '@/types'

// 搜索表单与分页
const searchForm = reactive<{ keyword: string; paymentStatus: string; dateRange: [string, string] | null }>({
  keyword: '',
  paymentStatus: '',
  dateRange: null,
})
const pagination = reactive({ page: 1, pageSize: 10, total: 0 })
const loading = ref(false)

// 源数据
const orders = ref<Order[]>([])
const receipts = ref<Receipt[]>([])
const customers = ref<Customer[]>([])

// 汇总信息
const summary = reactive({ overdueCount: 0, unpaidTotal: 0 })

// 收款对话框
const receiptDialog = reactive({
  visible: false,
  saving: false,
  unpaidRemain: 0,
  form: {
    orderId: '',
    orderNo: '',
    customerId: '',
    customerName: '',
    amount: 0,
    receiptDate: dayjs().format('YYYY-MM-DD'),
    method: 'transfer',
    remark: '',
  } as Omit<Receipt, 'id' | 'createTime' | 'updateTime'>,
})

/**
 * 计算支付状态对应的Element Plus Tag类型
 */
const getPaymentStatusType = (status: string) => {
  switch (status) {
    case 'paid': return 'success'
    case 'partial': return 'warning'
    case 'refunded': return 'info'
    default: return 'danger'
  }
}

/**
 * 解析客户付款条款中的天数（如："月结30天" => 30；"预付款" => 0；无法识别时默认30）
 */
function parsePaymentTermDays(term?: string): number {
  if (!term) return 30
  if (term.includes('预付款') || term.includes('现金')) return 0
  const m = term.match(/(\d+)\s*天/)
  if (m) return parseInt(m[1])
  if (term.includes('月结')) return 30
  return 30
}

/**
 * 计算订单应收到期日
 */
function calcDueDate(order: Order, customer: Customer | undefined): string {
  const base = order.deliveryDate ? dayjs(order.deliveryDate) : dayjs(order.createTime)
  const days = parsePaymentTermDays(customer?.paymentTerms)
  return base.add(days, 'day').format('YYYY-MM-DD')
}

/**
 * 聚合展示行：合并订单与收款记录，计算未收与逾期
 */
const displayRows = computed(() => {
  const receiptMap = receipts.value.reduce<Record<string, Receipt[]>>((acc, r) => {
    if (!acc[r.orderId]) acc[r.orderId] = []
    acc[r.orderId].push(r)
    return acc
  }, {})

  const customerMap = customers.value.reduce<Record<string, Customer>>((acc, c) => {
    acc[c.id] = c
    return acc
  }, {})

  let overdueCount = 0
  let unpaidTotal = 0

  const rows = orders.value.map(o => {
    const list = receiptMap[o.id] || []
    const paid = list.reduce((sum, r) => sum + Number(r.amount || 0), 0)
    const unpaid = Math.max(0, Number(o.finalAmount || 0) - paid)
    const dueDate = calcDueDate(o, customerMap[o.customerId])
    const isOverdue = unpaid > 0 && dayjs().isAfter(dayjs(dueDate))
    const overdueDays = isOverdue ? dayjs().diff(dayjs(dueDate), 'day') : 0

    if (isOverdue) overdueCount++
    unpaidTotal += unpaid

    return {
      ...o,
      receipts: list.sort((a, b) => a.receiptDate.localeCompare(b.receiptDate)),
      paidAmount: paid,
      unpaidAmount: unpaid,
      dueDate,
      overdueDays,
    }
  })

  summary.overdueCount = overdueCount
  summary.unpaidTotal = Number(unpaidTotal.toFixed(2))

  return rows
})

/**
 * 加载数据：订单、收款、客户
 */
async function fetchData() {
  try {
    loading.value = true
    // 订单
    const { data: orderResp } = await getOrderList({
      page: pagination.page,
      pageSize: pagination.pageSize,
      keyword: searchForm.keyword,
      paymentStatus: searchForm.paymentStatus || undefined,
      dateRange: searchForm.dateRange || undefined,
    })
    orders.value = orderResp.list
    pagination.total = orderResp.total

    // 收款记录（全部加载，体量可接受；如需可按orderId批量过滤）
    const { data: receiptResp } = await http.get<{ items: Receipt[] }>(`/receipts?page=1&pageSize=10000`)
    receipts.value = receiptResp.items || []

    // 客户映射
    const { data: customerResp } = await http.get<{ items: Customer[] }>(`/customers?page=1&pageSize=10000`)
    customers.value = customerResp.items || []
  } catch (e) {
    console.error(e)
    ElMessage.error('加载数据失败')
  } finally {
    loading.value = false
  }
}

/**
 * 重置查询
 */
function resetSearch() {
  searchForm.keyword = ''
  searchForm.paymentStatus = ''
  searchForm.dateRange = null
  pagination.page = 1
  fetchData()
}

/**
 * 打开新增收款对话框
 */
function openAddReceipt(row: any) {
  receiptDialog.visible = true
  receiptDialog.form.orderId = row.id
  receiptDialog.form.orderNo = row.orderNo
  receiptDialog.form.customerId = row.customerId
  receiptDialog.form.customerName = row.customerName
  receiptDialog.form.amount = Math.min(row.unpaidAmount, row.unpaidAmount) || 0
  receiptDialog.unpaidRemain = row.unpaidAmount
  receiptDialog.form.receiptDate = dayjs().format('YYYY-MM-DD')
  receiptDialog.form.method = 'transfer'
  receiptDialog.form.remark = ''
}

/**
 * 提交新增收款：写入receipts并联动更新订单支付状态
 */
async function submitReceipt() {
  if (!receiptDialog.form.amount || receiptDialog.form.amount <= 0) {
    ElMessage.warning('请输入有效的收款金额')
    return
  }
  try {
    receiptDialog.saving = true
    await http.post('/receipts', {
      ...receiptDialog.form,
    })

    // 重新加载收款
    const { data: receiptResp } = await http.get<{ items: Receipt[] }>(`/receipts`)
    receipts.value = receiptResp.items || []

    // 更新订单支付状态
    const order = orders.value.find(o => o.id === receiptDialog.form.orderId)
    if (order) {
      const paid = (receipts.value.filter(r => r.orderId === order.id).reduce((s, r) => s + Number(r.amount || 0), 0))
      const status = paid >= Number(order.finalAmount || 0) ? 'paid' : (paid > 0 ? 'partial' : 'unpaid')
      if (status !== order.paymentStatus) {
        await updatePaymentStatus(order.id, status)
        order.paymentStatus = status as any
      }
    }

    ElMessage.success('保存成功')
    receiptDialog.visible = false
  } catch (e) {
    console.error(e)
    ElMessage.error('保存收款失败')
  } finally {
    receiptDialog.saving = false
  }
}

/**
 * 删除收款记录
 */
async function deleteReceipt(r: Receipt) {
  try {
    await http.delete(`/receipts/${r.id}`)
    receipts.value = receipts.value.filter(x => x.id !== r.id)
    // 同步订单支付状态
    const order = orders.value.find(o => o.id === r.orderId)
    if (order) {
      const paid = (receipts.value.filter(x => x.orderId === order.id).reduce((s, x) => s + Number(x.amount || 0), 0))
      const status = paid >= Number(order.finalAmount || 0) ? 'paid' : (paid > 0 ? 'partial' : 'unpaid')
      if (status !== order.paymentStatus) {
        await updatePaymentStatus(order.id, status)
        order.paymentStatus = status as any
      }
    }
    ElMessage.success('已删除')
  } catch (e) {
    console.error(e)
    ElMessage.error('删除失败')
  }
}

/**
 * 展开/收起行
 */
function toggleExpand(row: any) {
  // 通过ref拿到表格实例进行toggle，但这里用简单方式：滚动到该行提示展开图标
  ElMessage.info('点击行首箭头可查看收款记录')
}

function onPageChange(p: number) { pagination.page = p; fetchData() }
function onPageSizeChange(s: number) { pagination.pageSize = s; pagination.page = 1; fetchData() }

/**
 * 行样式：逾期未清标红
 */
function rowClassName({ row }: any) {
  if (row.unpaidAmount > 0 && row.overdueDays > 0) return 'overdue-row'
  return ''
}

onMounted(fetchData)
</script>

<style scoped>
.settlement { padding: 0; }
.search-card { margin-bottom: 12px; }
.search-bar { display: flex; align-items: center; }
.header-row { display: flex; justify-content: space-between; align-items: center; }
.pager { margin-top: 12px; display: flex; justify-content: flex-end; }
.receipt-list { padding: 8px 0; }
.receipt-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }
.unpaid-tip { margin-left: 12px; color: #999; }
.overdue-row td { background-color: #fff3f3 !important; }
</style>